%%%-------------------------------------------------------------------
%%% @author wukai
%%% @copyright (C) 2017, <COMPANY>
%%% @doc
%%%
%%% @end
%%% Created : 07. 十一月 2017 11:58
%%%-------------------------------------------------------------------
-module(frame_sub).
-author("wukai").
-include("../include/mqtt_protocol.hrl").
%% API
-export([do_command/3]).
do_command(Ref, State, Frame) when Frame#mqtt_frame.frame_flag == 2 ->
  <<MsgId:16, Topics/binary>> = Frame#mqtt_frame.left_bytes,
  case topics(Topics, State#state.client) of
    {error, Info} ->
      lager:log(info, self(), "~p", [Info]),
      mqtt_process:exit_self();
    {ok, Subscribes} ->
      List = verify_topic(Subscribes),

      Tps = lists:foldl(fun(E, Acc) ->
        {Topic, R} = E,
        if R == true -> Acc ++ [Topic];
          true -> Acc end end, [], List),
%%      subscribe_server:send_sub(lists:filter(fun(E) -> {_, R} = E, R == true end, List), State#state.client, self()),
      subscribe_server:send_sub(Tps, State#state.client, self()),

      subscribe_ack(Ref, State, MsgId, code(List))
  end,
  State;

do_command(_, _, _) ->
  lager:log(info, self(), "disconnect frame_flag error"),
  mqtt_process:exit_self().


parse_topics(TopicsBin, List, Client) when byte_size(TopicsBin) > 0 ->
  try
    <<Tlen:16, Topic:Tlen/binary, Qos:8, Topics/binary>> = TopicsBin,

    %%校验当前Qos是否合法 否则断开连接
    case okmqtt_topic:qos_check(Qos) of
      false -> log:log("qos=~p value error ", [Qos]), mqtt_process:exit_self();
      _ -> do_nothing
    end,
    parse_topics(Topics, List ++ [{Topic, Qos}], Client)
  catch _:_ -> {error, "match binary errror"}
  end;
parse_topics(TopicsBin, List, _) when byte_size(TopicsBin) == 0 ->
  lager:log(info, self(), "topics ~p", [List]),
  {ok, List}.

%%解析主题过滤器
topics(Bin, _) when byte_size(Bin) == 0 ->
  lager:log(info, self(), "no topics subscribe"), {error, "no  subscribe topics"};
topics(Bin, Client) -> parse_topics(Bin, [], Client).


%%订阅确认消息
subscribe_ack(_, State, Msgid, Code) ->
  Len = 2 + erlang:byte_size(Code),
  mqtt_process:send_binary(State, <<?FRAME_SUB_ACK:4, 0:4, (protocol_util:len_bytes(Len))/binary, Msgid:?USHORT, Code/binary>>).


%%返回对应的主题过滤器是否订阅成功
code(L) -> code(L, <<>>).
code([H | T], Bin) ->
  case H of
    {_, false} -> Nbin = <<Bin/binary, 128:8>>,
      code(T, Nbin);
    {Filter2, true} ->
      {F, Q} = Filter2,
      Nbin = <<Bin/binary, Q:8>>,
      retain_server:retain_send(F, self()),
      code(T, Nbin)
  end;

code([], Bin) -> Bin.


verify_topic(Topics) ->
  verify_reg(Topics, []).
verify_reg([H | T], List) ->
  {Topic, _} = H,
  verify_reg(T, List ++ [{H, okmqtt_topic:topic_check(sub, Topic, other)}]);
verify_reg([], List) -> List.





